type Enum = { [s: number]: string }

/**
 * 检查枚举是否包含某个key
 */
export function isEnumKey<T extends Enum>(enumSrc: T, key: unknown): key is keyof T {
  return Number.isInteger(enumSrc[key as keyof T])
}

/**
 * 检查枚举是否包含某个value
 */
export function isEnumValue<T extends Enum>(enumSrc: T, value: unknown): value is T[keyof T] {
  return Number.isInteger(enumSrc[enumSrc[value as keyof T] as any as keyof T])
}

/**
 * 将枚举转化为key列表
 */
export function enumToKeys<T extends Enum>(enumSrc: T): (keyof T)[] {
  return Object.keys(enumSrc).filter((key: keyof T | any) => isEnumKey(enumSrc, key)) as (keyof T)[]
}

/**
 * 将枚举转化为value列表
 */
export function enumToValues<T extends Enum>(enumSrc: T): T[keyof T][] {
  return enumToKeys(enumSrc).map((key: keyof T) => enumSrc[key])
}

/**
 * 将枚举值转化为对应的key
 */
export function enumValueToKey<T extends Enum>(enumSrc: T, value: T[keyof T]): keyof T | undefined {
  return (enumSrc as any)[value]
}

/**
 * 将枚举转换为键值对数组
 */
export function enumToEntries<T extends Enum>(enumSrc: T): [keyof T, T[keyof T]][] {
  return enumToValues(enumSrc).map((value: T[keyof T]) => [enumValueToKey(enumSrc, value) as keyof T, value])
}

/**
 * 将枚举转换为对象数组
 */
export function fromEnum<T extends Enum, C>(enumSrc: T, projection: (item: [keyof T, T[keyof T]], index: number, array: [keyof T, T[keyof T]][]) => C, skip?: (value: [keyof T, T[keyof T]], index: number, array: [keyof T, T[keyof T]][]) => boolean) {
  let entries = enumToEntries(enumSrc)
  if (skip) entries = entries.filter(skip)
  return entries.map(projection)
}
